package edu.hawaii.duedates.lender;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import com.meterware.httpunit.WebConversation;

/**
 * An abstract representation of a Lender-Borrower relationship which is extended to specify due
 * date data collection depending on Lender criteria and user needs.
 * 
 * @author Aric West
 * @author Daniel Tian
 * 
 */
public abstract class Lender implements Comparable<Lender> {
  protected String lenderName;
  protected List<BorrowedItem> itemList;
  protected String logonFormName;
  protected String field1Name;
  protected String field2Name;
  protected String field1Value;
  protected String field2Value;
  protected String url;
  protected WebConversation conversation;
  protected String loginFailedText;
  
  /**
   * Whether the system logged on the user or not.
   */
  public boolean loggedOn;
  
  /**
   * Constructor. Instantiates the WebConversation and item list.
   */
  public Lender() {
    this.conversation = new WebConversation();
    this.itemList = new ArrayList<BorrowedItem>();
  }
  
  /**
   * Sets the fields required to log into the system.
   * 
   * @param f1 first field
   * @param f2 second field
   */
  public void setLoginFields(String f1, String f2) {
    this.field1Value = f1;
    this.field2Value = f2;
  }
  
  /**
   * Logs into the lender system with the provided fields.
   * 
   * @throws LogInException If an error occurred that prevented login.
   */
  public abstract void logIn() throws LogInException;
  
  /**
   * Parses the source of information holding borrowed items and due date information.  This is
   * often from a table.
   * 
   * @throws ParseItemException If an error occurred that prevented successful parsing.
   * @throws LogInException If an error occurred that prevented login.
   */
  public abstract void queryBorrowedItems() throws ParseItemException, LogInException;
  
  /**
   * Returns the number of fields this class needs to log into the UH library system.
   * 
   * @return the number of fields
   */
  
  /**
   * Returns the lender's name.
   * 
   * @return The lender's name.
   */
  public String getLenderName() {
    return lenderName;
  }
  
  /**
   * Returns the list of borrowed items.
   * 
   * @return The list of borrowed items.
   */
  public List<BorrowedItem> getItemList() {
    return itemList;
  }
  
  /**
   * Returns a list of borrowed items due before a certain date.
   * 
   * @param withinDate The date that the items are due before.
   * @return A list of borrowed items due before the specified date.
   */
  public List<BorrowedItem> getItemListWithinDate(Calendar withinDate) {
    List<BorrowedItem> withinList = new ArrayList<BorrowedItem>();
    
    for (BorrowedItem item : this.itemList) {
      if (item.getDueDate().before(withinDate)) {
        withinList.add(item);
      }
    }
    
    return withinList;
  }
  
  /**
   * Sorts the item list by earliest due date.
   */
  public void sort() {
    Collections.sort(this.itemList);
  }
  
  /**
   * Compares the this LenderQuery object to another to determine order.
   * 
   * @param lq The LenderQuery object being compared to.
   * @return Value of ordering.
   */
  public int compareTo(Lender lq) {
    return this.getLenderName().compareTo(lq.getLenderName());
  }
  
  /**
   * Returns whether this object is equal to the passed object.
   * 
   * @param o The object to compare this object to.
   * @return Whether this object is equal to the o object.
   */
  public abstract boolean equals(Object o);
  
  /**
   * Creates a hash code for this instance.
   * 
   * @return The hash code for this instance.
   */
  public abstract int hashCode();
  
  /**
   * Returns the lender name and number of items checked out as a string.
   * 
   * @return A string of the lender name and the number of items that are checked out.
   */
  public String toString() {
    return this.lenderName + " has " + this.itemList.size() + " items checked out.";
  }
}